﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Http;
using System.Net.Http;
using System.Web.Http.ModelBinding;
using System.Web.Security;

using ERPStore.Web.Extensions;
using ERPStore.Cart.Models;

using CloudSoft.Extensions;

namespace ERPStore.Web.Cart.Controllers
{
	public class CartApiController : ApiController
	{
		public CartApiController(ERPStore.Cart.Services.CartService cartService
			, ERPStore.Cart.Services.AdminCartService adminCartService
			, ERPStore.Services.ICatalogService catalogService
			, ERPStore.Services.IOffersService offerService
			, ERPStore.Services.IIncentiveService incentiveService
			, ERPStore.Services.IAccountService accountService
			, ERPStore.Services.ISalesService salesService
			, ERPStore.Logging.ILogger logger
			)
		{
			this.CartService = cartService;
			this.AdminCartService = adminCartService;
			this.CatalogService = catalogService;
			this.OfferService = offerService;
			this.IncentiveService = incentiveService;
			this.AccountService = accountService;
			this.SalesService = salesService;
			this.Logger = logger;
		}

		protected ERPStore.Cart.Services.CartService CartService { get; private set; }
		protected ERPStore.Cart.Services.AdminCartService AdminCartService { get; private set; }
		protected ERPStore.Services.ICatalogService CatalogService { get; private set; }
		protected ERPStore.Services.IOffersService OfferService { get; private set; }
		protected ERPStore.Services.IIncentiveService IncentiveService { get; private set; }
		protected ERPStore.Services.IAccountService AccountService { get; private set; }
		protected ERPStore.Services.ISalesService SalesService { get; private set; }
		protected ERPStore.Logging.ILogger Logger { get; private set; }

		[HttpGet]
		public DateTime Ping()
		{
			return DateTime.Now;
		}

		protected virtual new ERPStore.Models.UserPrincipal User
		{
			get
			{
				return base.User as ERPStore.Models.UserPrincipal;
			}
		}

		public ERPStore.Cart.ViewModels.CartViewModel GetCurrent()
		{
			var cart = CartService.GetCurrentCart(User);

			if (cart == null)
			{
				return null;
			}

			cart.PrepareToView(
				User
				, OfferService
				, SalesService
				, AccountService
				, IncentiveService
				, CartService);

			cart.PrepareToSerialize();

			return AutoMapper.Mapper.Map<ERPStore.Cart.ViewModels.CartViewModel>(cart);
		}

		public ERPStore.Cart.ViewModels.CartViewModel GetCartByCode(string id)
		{
			if (id.IsNullOrTrimmedEmpty())
			{
				throw new ArgumentException("code does not be null or empty");
			}

			var cart = CartService.GetCartByCode(id);

			if (cart == null)
			{
				throw new ArgumentException("this cart id does not exists");
			}

			cart.PrepareToView(
				User
				, OfferService
				, SalesService
				, AccountService
				, IncentiveService
				, CartService);

			cart.PrepareToSerialize();

			return AutoMapper.Mapper.Map<ERPStore.Cart.ViewModels.CartViewModel>(cart);
		}

		public void PutCartItem([FromUri]string productCode, [FromUri]int quantity = 1, [FromUri]string offerName = null, [FromUri]string addFrom = null)
		{
			var product = CatalogService.GetProductByCode(productCode);
			if (product == null)
			{
				return;
			}

			var cart = CartService.GetOrCreateCart(User);

			if (cart.ConvertedEntityId.HasValue)
			{
				throw new Exception("this cart is already converted");
			}

			OfferService.ApplyOffers(product, User.CurrentUser);
			quantity = GetQuantity(product, quantity);

			if (product.SelectedOffer != null)
			{
				offerName = product.SelectedOffer.Name;
			}

			CartService.AddCartItem(cart, product, quantity, offerName, Request.GetClientIpAddress(), addFrom);
			IncentiveService.Recalc(cart, User);
			SalesService.CalculateShippingFee(cart, User);

			using (var ts = TransactionHelper.GetNewReadCommitted())
			{
				CartService.Save(cart);
				ts.Complete();
			}
		}

		public void DeleteCartItem(int id)
		{
			var cart = CartService.GetOrCreateCart(User);

			if (cart.ConvertedEntityId.HasValue)
			{
				throw new Exception("this cart is already converted");
			}

			CartService.RemoveCartItem(cart, id);
			IncentiveService.Recalc(cart, User);

			using (var ts = TransactionHelper.GetNewReadCommitted())
			{
				CartService.Save(cart);
				ts.Complete();
			}
		}

		public void PostCartItemQuantity([FromUri] int index, [FromUri] int quantity)
		{
			var cart = CartService.GetCurrentCart(User);
			if (cart == null)
			{
				return;
			}

			if (cart.ConvertedEntityId.HasValue)
			{
				throw new Exception("this cart is already converted");
			}

			if (index > cart.ItemCount)
			{
				return;
			}

			CartService.RecalcCartItem(cart.Items[index], quantity);
			IncentiveService.Recalc(cart, User);
			CartService.Save(cart);
		}

		private void PrepareProduct(ERPStore.Models.Product product)
		{
			if (product.Brand != null
				&& product.Brand.DefaultImage != null)
			{
				product.Brand.DefaultImage.ExternalUrl = null;
			}

			if (product.Category != null
				&& product.Category.DefaultImage != null)
			{
				product.Category.DefaultImage.ExternalUrl = null;
			}

			if (product.DefaultImage != null)
			{
				product.DefaultImage.ExternalUrl = null;
			}

			product.OrderCount = 0;

			if (product.Stats != null)
			{
				product.Stats.DistinctCustomerCount = 0;
				product.Stats.OrderCount = 0;
				product.Stats.SaleTotal = 0;
				product.Stats.VisitorCount = 0;
			}

			if (product.SelectedOffer != null)
			{
				var so = product.SelectedOffer;

				var offer = new ERPStore.Models.Offer()
				{
					CSSTag = product.SelectedOffer.CSSTag,
					Description = product.SelectedOffer.Description,
					EndDate = product.SelectedOffer.EndDate,
					Link = product.SelectedOffer.Link,
					Name = product.SelectedOffer.Name,
					PhysicalStockMandatory = product.SelectedOffer.PhysicalStockMandatory,
					StartDate = product.SelectedOffer.StartDate,
					Title = product.SelectedOffer.ViewName,
					ViewName = product.SelectedOffer.ViewName,
				};

				product.SelectedOffer = offer;
			}
			product.OfferList = null;
		}

		private int GetQuantity(ERPStore.Models.Product product, object qty)
		{
			var quantity = product.Packaging.Value;
			if (!int.TryParse(qty.ToString(), out quantity))
			{
				quantity = product.Packaging.Value;
			}
			quantity = Math.Max(Math.Max(product.MinimumSaleQuantity, 1), quantity);
			var mod = quantity % product.Packaging.Value;
			mod = (mod == 0 ? 0 : 1);
			var ratio = (quantity / product.Packaging.Value);
			quantity = (ratio + mod) * product.Packaging.Value;
			return quantity;
		}

	}
}
